<!-- 图层控制 -->
<template>
  <div v-if="layerControl" class="layer-control">
    <div class="check-all">
      <span class="layer-gltext">图层管理</span>
      <a-checkbox v-model:checked="checkAll" :indeterminate="indeterminate" @change="onCheckAllChange">
        全选
      </a-checkbox>
    </div>
    <a-divider />
    <div class="check-last">
      <a-checkbox-group v-model:value="checkedList" :options="plainOptions" @change="onCheckChange" />
    </div>
    <!-- <a-divider />
    <div class="style-name">
      <a-button @click="clearAllLayer">删除所有图层</a-button>
    </div> -->
    <a-divider />
    <div class="style-switching" @click="styleChange">
      <swap-outlined /> 风格切换
    </div>
    <div class="style-name">
      ( {{ buildingStyle ? "简化版" : "精细模型版" }} )
    </div>
    <a-divider />
    <div class="style-name">
      <a-button :disabled="buildingStyle" @click.stop="openFile">
        <DownloadOutlined />
        导入模型
      </a-button>
      <input ref="exportGltf" type="file" accept=".glb" hidden @change="exportModel" />
      <a-button style="margin-left: 20px" @click="exportJsonFile">
        <template #icon>
          <upload-outlined />
        </template>
        导出模型配置文件
      </a-button>
    </div>
    <a-divider />
    <div class="style-name">
      <a-button @click.stop="show3DTiles">
        <DownloadOutlined />
        加载倾斜摄影
      </a-button>
      <a-button style="margin-left: 20px" @click.stop="showChartletLyer">
        <DownloadOutlined />
        加载贴图建筑
      </a-button>
    </div>
    <a-divider />
    <div class="style-name">
      <a-button @click.stop="showFloorBuildingLayer">
        <DownloadOutlined />
        加载分层建筑
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(1)">
        1
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(2)">
        2
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(3)">
        3
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(4)">
        4
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(5)">
        5
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(6)">
        6
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(7)">
        7
      </a-button>
      <a-button style="margin-left: 10px" @click.stop="selectFloor(8)">
        8
      </a-button>
    </div>
  </div>
  <ModelLayer ref="modelLayer" />
  <TilesLayer ref="tilesLayer" />
  <ChartletLyer ref="chartletLyer" />
  <BuildingLayer ref="buildingLayer" />
</template>

<script>
import mapboxgl from 'mapbox-gl'
import {
  reactive,
  toRefs,
  onMounted,
  getCurrentInstance,
  watch,
  ref
} from 'vue'
import api from '../../api/geoserver'
import axios from 'axios'
import {
  SwapOutlined,
  DownloadOutlined,
  UploadOutlined
} from '@ant-design/icons-vue'
import { message } from 'ant-design-vue'
import ModelLayer from './ModelLayer.vue'
import TilesLayer from './TilesLayer.vue'
import ChartletLyer from './ChartletLyer.vue'
import BuildingLayer from './BuildingLayer.vue'
import { exportJson } from '../../utils/xingutils.js'
import { mainStore } from '../../store/index.js'
import { THREE } from 'threebox-plugin'

export default {
  components: {
    SwapOutlined,
    DownloadOutlined,
    UploadOutlined,
    ModelLayer,
    TilesLayer,
    ChartletLyer,
    BuildingLayer
  },
  setup() {
    const state = reactive({
      layerControl: false,
      indeterminate: false,
      checkAll: true,
      checkedList: [],
      buildingStyle: true,
      plainOptions: [],
      chartletbuild: false
    })
    const modelLayer = ref(null)
    const tilesLayer = ref(null)
    const exportGltf = ref(null)
    const chartletLyer = ref(null)
    const buildingLayer = ref(null)
    const { proxy } = getCurrentInstance()
    const map = proxy.$root.$map
    const parameter = {
      service: 'WFS',
      version: '1.0.0',
      request: 'GetFeature',
      maxFeatures: '10000',
      outputFormat: 'application/json'
    }
    const popups = []

    let schoolInfo, uploadHide
    const config = proxy.$root.$mapconfig,
      store = mainStore(),
      allMapLayerIds = store.allMapLayerIds,
      path = import.meta.env.VITE_APP_PATH
    // let plainOptions = [];

    onMounted(() => {
      // loadDatas();
      addControl()
      addImageSource()
      loadLayerJson('sqsfxq')
    })

    watch(
      () => state.checkedList,
      (val) => {
        state.indeterminate =
          Boolean(val.length) && val.length < state.plainOptions.length
        state.checkAll = val.length === state.plainOptions.length
      }
    )

    // 加载图层数据
    async function loadDatas() {
      map.addSource('wms-test-source', {
        type: 'raster',
        // use the tiles option to specify a WMS tile source URL
        // https://docs.mapbox.com/mapbox-gl-js/style-spec/sources/
        tiles: [
          'http://39.105.214.6:8081/geoserver/gwc/service/wmts?layer=sqsf:sqsf_baselayers&style=&tilematrixset=EPSG:900913&Service=WMTS&Request=GetTile&Version=1.0.0&Format=image/png&TileMatrix=EPSG:900913:{z}&TileCol={x}&TileRow={y}'
        ],
        tileSize: 256
      })
      map.addLayer({
        id: 'wms-test-layer',
        type: 'raster',
        source: 'wms-test-source',
        paint: {}
      })

      const roomData = await api
        .getData2(parameter)
        .catch((err) => console.log(err))

      parameter.typeName = 'sqsfgx:dlmc_point'
      const roadData = await api
        .getData(parameter)
        .catch((err) => console.log(err))

      map.addSource('dlmc_point', {
        type: 'geojson',
        data: roadData
      })
      console.log('roomData', roomData)

      map.addSource('roomData', {
        type: 'geojson',
        data: roomData
      })
      map.addLayer({
        id: 'buildings',
        type: 'fill-extrusion', //设置当前图层类型 此为边
        source: 'roomData',
        layout: {
          visibility: 'visible' //是否显影
        },
        paint: {
          //设置属性
          'fill-extrusion-color': ['get', 'color'],
          'fill-extrusion-height': [
            'interpolate',
            ['linear'],
            ['zoom'],
            15,
            0,
            15.05,
            ['get', 'height']
          ],
          'fill-extrusion-base': [
            'interpolate',
            ['linear'],
            ['zoom'],
            15,
            0,
            15.05,
            ['get', 'min_height']
          ],
          'fill-extrusion-opacity': 0.6
        }
      })

      parameter.typeName = 'sqsf:outside_jianzhuwu'
      const outbuildingData = await api
        .getData2(parameter)
        .catch((err) => console.log(err))

      map.addSource('outside_jianzhuwu', {
        type: 'geojson',
        data: outbuildingData
      })
      map.addLayer({
        id: 'outbuildings',
        type: 'fill-extrusion', //设置当前图层类型 此为边
        source: 'outside_jianzhuwu',
        layout: {
          visibility: 'visible' //是否显影
        },
        paint: {
          //设置属性
          'fill-extrusion-color': '#bfeeec',
          'fill-extrusion-height': [
            'interpolate',
            ['linear'],
            ['zoom'],
            15,
            0,
            15.05,
            ['get', 'height']
          ],
          'fill-extrusion-base': [
            'interpolate',
            ['linear'],
            ['zoom'],
            15,
            0,
            15.05,
            ['get', 'min_height']
          ],
          'fill-extrusion-opacity': 0.6
        }
      })

      map.loadImage('/images/lable/lable1.png', (error, image) => {
        if (error) {
          throw error
        }
        // Add the loaded image to the style's sprite with the ID 'kitten'.
        map.addImage('lable-1', image, {
          stretchX: [
            [28, 48],
            [86, 106]
          ],
          stretchY: [[15, 45]],
          content: [28, 15, 106, 45],
          pixelRatio: 2
        })
        map.addLayer({
          id: 'original',
          type: 'symbol',
          source: 'dlmc_point',
          layout: {
            'text-field': ['get', 'name'],
            'icon-image': 'lable-1',
            'icon-text-fit': 'both',
            'icon-allow-overlap': false,
            'text-allow-overlap': false,
            'text-size': 12
          },
          paint: {
            'text-color': 'rgb(54,153,255)'
          }
        })
      })

      parameter.typeName = 'sqsf:shumu'
      const treeData = await api
        .getData2(parameter)
        .catch((err) => console.log(err))

      console.log('树木', treeData)
      map.addSource('shumu', {
        type: 'geojson',
        data: treeData
      })

      map.addLayer({
        id: 'shumu',
        type: 'symbol',
        source: 'shumu',
        layout: {
          'icon-image': ['get', 'alias'],
          'icon-allow-overlap': false,
          'text-allow-overlap': false
        }
      })

      parameter.typeName = 'sqsf:jianzhuwulabel'
      const buildingLabelData = await api
        .getData2(parameter)
        .catch((err) => console.log(err))

      map.addSource('jianzhuwulabel', {
        type: 'geojson',
        data: buildingLabelData
      })
      map.addLayer({
        id: 'jianzhuwulabel',
        type: 'symbol',
        source: 'jianzhuwulabel',
        layout: {
          'text-field': ['get', 'name'],
          'text-size': 11,
          'text-letter-spacing': 0.2,
          'text-offset': [0, -1]
        },
        paint: {
          'text-color': '#181818',
          'text-halo-color': 'rgba(255, 255,255, 1)', // 光影效果
          'text-halo-width': 1.5 // 光影效果
        }
      })

      map.U.clickLayer('buildings', (e) => {
        removePopups()
        const name = e.features[0].properties.name
        // console.log('featureProperties', e);
        // const position2D = featureProperties.lonlatTwodim.split(',')

        if (name) {
          const popupHtml2D = '<div class="popup-simple">' + name + '</div>',
            popup = new mapboxgl.Popup({
              className: 'map-click-popup',
              maxWidth: '400px',
              closeButton: false,
              offset: [0, -15]
            }).setHTML(popupHtml2D)

          popup.setLngLat(e.lngLat).addTo(map)
          popups.push(popup)
        }
        e.preventDefault()
      })
    }

    // 加载树图片源
    function addImageSource() {
      const images = {
        heihuaishu: path + 'images/treeflower/heihuaishu.png',
        hua: path + 'images/treeflower/hua.png',
        liushu: path + 'images/treeflower/liushu.png',
        songbai: path + 'images/treeflower/songbai.png',
        wutong: path + 'images/treeflower/wutong.png',
        yangshu: path + 'images/treeflower/yangshu.png'
      }

      for (const key in images) {
        map.loadImage(images[key], (error, image) => {
          if (error) {
            throw error
          }
          if (key === 'songbai') {
            map.addImage(key, image, {
              pixelRatio: 16
            })
          } else {
            map.addImage(key, image, {
              pixelRatio: 10
            })
          }
        })
      }
    }

    // 加载配置文件中图层信息
    async function loadLayerJson(schValue) {
      clearAllLayer()
      config.campus.some((sch) => {
        if (sch.value === schValue) {
          schoolInfo = sch
          return true
        }
      })
      // 改变校区显示区域
      map.setCenter(schoolInfo.center)
      console.log('图层信息', schoolInfo)
      disposalLayers()
      initLayerList()
    }

    // 处理图层数据
    async function disposalLayers() {
      // 加载底图
      for (const item of schoolInfo.basemaps) {
        allMapLayerIds.push(item.layerId)
        if (!map.getSource(item.sourceId)) {
          map.addSource(item.sourceId, item.sourceOptions)
        }
        addLayerItem(item)
      }
      // 加载图层
      for (const item of schoolInfo.layers) {
        // console.log('图层', item);
        allMapLayerIds.push(item.layerId)
        if (!item.show) {
          continue
        }
        parameter.typeName = item.layer
        const groupName = item.layer.split(':')[0],
          data = await api
            .getLayerData(groupName, parameter)
            .catch((err) => console.log(err))

        // 添加数据源
        if (!map.getSource(item.sourceId)) {
          map.addSource(item.sourceId, {
            type: 'geojson',
            data: data
          })
        }
        // 判断是否有标签图标
        if (item.imageId) {
          if (map.hasImage(item.imageId)) {
            addLayerItem(item)
          } else {
            map.loadImage(path + item.imageUrl, (error, image) => {
              if (error) {
                throw error
              }
              map.addImage(item.imageId, image, item.imageOptions)
              addLayerItem(item)
            })
          }
        } else {
          addLayerItem(item)
        }
        // 图层添加完成后注册图层点击事件
        if (item.name === '校内建筑') {
          addListener(item.layerId)
        }
      }
    }

    // 添加图层
    function addLayerItem(item) {
      // 判断图层是否已经添加
      const layer = map.getLayer(item.layerId)

      if (layer) {
        map.U.show(item.layerId)
      } else {
        map.addLayer({
          id: item.layerId,
          source: item.sourceId,
          type: item.style.type,
          layout: item.style.layout || {},
          paint: item.style.paint || {}
        })
      }
    }

    // 添加监听
    function addListener(layerId) {
      map.U.clickLayer(layerId, (e) => {
        removePopups()
        const name = e.features[0].properties.name

        console.log('featureProperties', e.features[0])
        // const position2D = featureProperties.lonlatTwodim.split(',')
        if (name) {
          const popupHtml2D = '<div class="popup-simple">' + name + '</div>',
            popup = new mapboxgl.Popup({
              className: 'map-click-popup',
              maxWidth: '400px',
              closeButton: false,
              offset: [0, -15]
            }).setHTML(popupHtml2D)

          popup.setLngLat(e.lngLat).addTo(map)
          popups.push(popup)
        }
        e.preventDefault()
      })
    }

    // 初始化图层列表
    function initLayerList() {
      for (const item of schoolInfo.layers) {
        state.plainOptions.push(item.name)
        if (item.show) {
          state.checkedList.push(item.name)
        }
      }
      state.layerControl = true
      console.log(state.checkedList, state.plainOptions, state.checkAll)
    }

    // 全选框改变
    function onCheckAllChange(e) {
      Object.assign(state, {
        checkedList: e.target.checked ? state.plainOptions : [],
        indeterminate: false
      })
      showlayer()
    }

    // 单选框改变
    function onCheckChange(e) {
      console.log(state.checkedList)
      showlayer()
      console.log('allMapLayerIds', allMapLayerIds)
    }

    // 图层显示隐藏控制
    function showlayer() {
      for (const name of state.plainOptions) {
        const isShow = state.checkedList.includes(name)

        schoolInfo.layers.some((layer) => {
          if (layer.name === name) {
            // console.log(layer, isShow);
            if (isShow) {
              // map.setLayoutProperty(layer.layerId, "visibility", "visible");
              map.U.show(layer.layerId)
            } else {
              // map.setLayoutProperty(layer.layerId, "visibility", "none");
              map.U.hide(layer.layerId)
            }
            return true
          }
        })
      }
    }

    // 添加控件
    function addControl() { }

    // 关闭弹窗
    function removePopups() {
      popups.forEach((popup, index, arr) => {
        popup.remove()
      })
    }

    // 风格切换
    function styleChange() {
      state.buildingStyle = !state.buildingStyle
      if (state.buildingStyle) {
        // 展示建筑图层
        map.U.hide(schoolInfo.modelLayerid)
        for (const layer of schoolInfo.layers) {
          if (layer.name === '校内建筑' || layer.name === '校外建筑') {
            map.U.show(layer.layerId)
          }
        }
      } else {
        for (const layer of schoolInfo.layers) {
          if (layer.name === '校内建筑' || layer.name === '校外建筑') {
            map.U.hide(layer.layerId)
          }
        }
        // 判断场景中是否有模型图层
        const stateDataLayer = map.getLayer(schoolInfo.modelLayerid)

        if (stateDataLayer) {
          map.U.show(schoolInfo.modelLayerid)
          showModelLayer()
        } else {
          // 调用添加模型方法
          modelLayer.value.loadLayerJson(schoolInfo)
        }
      }
    }

    // 显示模型图层
    function showModelLayer() {
      schoolInfo.layers.some((layer) => {
        if (layer.name === '校内建筑') {
          map.moveLayer(schoolInfo.modelLayerid, layer.layerId)
          return true
        }
      })
    }

    // 导出模型调整位置后的配置文件
    function exportJsonFile() {
      console.log('导出文件', tb)
      const modelList = tb.scene.children[0].children,
        modelJson = {
          models: [],
          type: 'modelCollection',
          opacityZoom: 18
        }

      for (const modelObj of modelList) {
        if (modelObj.userData.belong !== schoolInfo.model) {
          continue
        }
        const modelInfo = {
          name: modelObj.userData.name,
          type: modelObj.userData.type,
          obj: modelObj.userData.zqobj,
          belong: modelObj.userData.belong,
          units: modelObj.userData.units,
          scale: modelObj.userData.scale,
          rotation: modelObj.userData.rotation,
          anchor: modelObj.userData.anchor,
          position: modelObj.userData.position
        }

        modelInfo.position = modelObj.coordinates
        modelInfo.rotation.y =
          modelInfo.rotation.y +
          Number((modelObj.rotation.z * 180 / Math.PI).toFixed(0))
        // console.log("整理模型信息", modelInfo);
        modelJson.models.push(modelInfo)
      }
      console.log('模型json', modelJson)
      exportJson(modelJson, schoolInfo.model)
    }

    // 清除地图上所有图层
    function clearAllLayer() {
      state.plainOptions = []
      state.checkedList = []

      for (const id of allMapLayerIds) {
        if (map.getLayer(id)) {
          map.removeLayer(id)
        }
      }
      store.$patch({
        allMapLayerIds: []
      })
      state.buildingStyle = true
      if (schoolInfo && map.getLayer(schoolInfo.modelLayerid)) {
        map.U.hide(schoolInfo.modelLayerid)
      }
    }

    // 打开文件选择框
    function openFile() {
      exportGltf.value.click()
    }

    // 上传文件模型改变
    const key = 'updatable'

    function exportModel(file) {
      const f = file.target.files[0]

      if (f?.name.includes('.glb')) {
        loadPathModel(f)
        message.loading({ content: '模型上传中...', key })
      } else {
        message.error('请打开规定格式文件！')
      }
    }

    // 加载模型
    function loadPathModel(fileInfo) {
      const name = fileInfo.name,
        dataURL = URL.createObjectURL(fileInfo),
        { lng, lat } = map.getCenter(),
        // console.log('信息', name, dataURL);
        model = {
          name: name.split('.')[0],
          type: 'glb',
          belong: schoolInfo.model,
          zqobj: dataURL,
          obj: dataURL,
          units: 'meters',
          scale: 1,
          rotation: {
            x: 90,
            y: 0,
            z: 0
          },
          anchor: 'center',
          position: [lng, lat, 0]
        }

      tb.loadObj(model, function (mo) {
        const soldier = mo.setCoords(model.position)

        soldier.uuid = model.name
        soldier.traverse((e) => {
          if (e.material) {
            e.material.format = THREE.RGBAFormat
            if (model.belong === 'zdmodels.json') {
              e.material.color.offsetHSL(0, 0, -0.3)
              e.material.emissive = e.material.color
              e.material.emissiveMap = e.material.map
            }
          }
        })
        tb.add(soldier)
        message.success({ content: '上传成功!', key, duration: 2 })
      })
    }

    // 加载倾斜摄影
    function show3DTiles() {
      tilesLayer.value.show3DTiles()
    }

    // 加载贴图建筑
    function showChartletLyer() {
      state.chartletbuild = !state.chartletbuild
      if(state.chartletbuild) {
        const stateDataLayer = map.getLayer('sqsfchartlet_layer')
        if (stateDataLayer) {
          map.U.show('sqsfchartlet_layer')
        }else{
          chartletLyer.value.loadLayerJson()
        }
      }else{
        map.U.hide('sqsfchartlet_layer')
      }
    }

    // 加载分层建筑
    function showFloorBuildingLayer() {
      buildingLayer.value.loadLayerJson()
    }

    // 楼层分层动画
    function selectFloor(floor) {
      buildingLayer.value.selectFloor(floor)
    }

    return {
      modelLayer,
      tilesLayer,
      chartletLyer,
      buildingLayer,
      exportGltf,
      ...toRefs(state),
      onCheckAllChange,
      onCheckChange,
      styleChange,
      exportJsonFile,
      loadLayerJson,
      clearAllLayer,
      openFile,
      exportModel,
      show3DTiles,
      showChartletLyer,
      showFloorBuildingLayer,
      selectFloor
    }
  }
}
</script>
<style lang='scss' scoped>
.layer-control {
  width: 335px;
  padding-bottom: 24px;
  // background: hsla(0, 0%, 100%, 0.9);
  // -webkit-box-shadow: 0 2px 4px 0 rgba(195, 192, 192, 0.75);
  // box-shadow: 0 2px 4px 0 rgba(74, 71, 71, 0.75);
  // border-radius: 2px;

  :deep(.ant-checkbox-group-item) {
    margin-bottom: 15px;
    min-width: 115px;
  }
  .check-all {
    padding: 0px 0 0 20px;

    .layer-gltext {
      margin-right: 55px;
      font-size: 15px;
      font-weight: 700;
      letter-spacing: 2px;
    }
  }

  .check-last {
    padding: 0 20px;
  }

  .style-switching {
    display: inline-block;
    padding-left: 20px;
    cursor: pointer;
    color: rgba(0, 0, 0, 0.85);
  }

  .style-switching:hover {
    color: #47a9f3;
  }

  .style-name {
    display: inline-block;
    padding-left: 20px;
  }
}
</style>
